#include "videoreceiver.h"
#include <QDebug>
#include <QImage>
#include "videowindow.h"

VideoReceiver::VideoReceiver(QWidget* control, quint16 listenPort, QString ip, QString infName, int bindWay, QObject *parent) : QObject(parent),
    m_recThread(nullptr),
    m_recWork(nullptr),
    m_listenPort(listenPort),
    m_ip(ip),
    m_infName(infName),
    m_control(control),
    m_bindWay(bindWay),
    m_player(nullptr)
{
    m_recThread = new QThread;
    m_recWork = new ReceiveWork(m_listenPort, m_ip, m_infName, &m_frameQueue, m_bindWay);

    connect(m_recThread, &QThread::finished, m_recWork, &QObject::deleteLater);
    connect(this, &VideoReceiver::sig_init, m_recWork, &ReceiveWork::init);
    connect(this, &VideoReceiver::sig_start, m_recWork, &ReceiveWork::startReceiving);
    connect(this, &VideoReceiver::sig_stop, m_recWork, &ReceiveWork::stopReceiving);
    connect(this, &VideoReceiver::sig_close, m_recWork, &ReceiveWork::closeAll);

    //连接work线程到主线程
    connect(m_recWork, &ReceiveWork::sigSendDataToSave, this, &VideoReceiver::sigSendDataToSave); //转存
    connect(m_recWork, &ReceiveWork::sig_initRet, [=](bool ret){
        initRet = ret;
    });
    connect(m_recWork, &ReceiveWork::sigSrcIP, this, &VideoReceiver::sigSrcIP);

    m_recWork->moveToThread(m_recThread);
    m_recThread->start();

    //创建定时器发送QImage
    //m_timer = new QTimer;
    //connect(m_timer, &QTimer::timeout, this, &VideoReceiver::onTimer);
}

VideoReceiver::~VideoReceiver()
{
    emit sig_close();
}

void VideoReceiver::init()
{
    emit sig_init();
}

void VideoReceiver::startReceiving()
{
    if(m_player) {
        delete m_player;
    }
    m_player = new GstVideoPlayer(m_control, this);
    connect(m_recWork, &ReceiveWork::frameToGStream, m_player, &GstVideoPlayer::onUdpDataReceived);
    connect(m_player, &GstVideoPlayer::newImageAvailable, this, &VideoReceiver::sigFrameAvailable);
    connect(m_player, &GstVideoPlayer::videoInfoChanged, this, &VideoReceiver::sigVideoInfoChanged);

    m_player->startPlayback(m_ip, m_listenPort);

    //m_timer->start(50);
    emit sig_start();
}

void VideoReceiver::stopReceiving()
{
    //m_timer->stop();

    emit sig_stop();
    m_player->stopPlayback();
}

void VideoReceiver::resetSettings(QString ip, quint16 listenPort, QString m_infName, int bindWay)
{
    m_ip = ip;
    m_listenPort = listenPort;
    m_bindWay = bindWay;

    stopReceiving();
    init();
    m_recWork->setNetInfo(ip, listenPort, m_infName);
    startReceiving();
}

void VideoReceiver::onTimer()
{
    if(!m_frameQueue.isEmpty()) {
        emit frameReceived(m_frameQueue.dequeue());
    }
}

void ReceiveWork::onReceive()
{
    while (m_socket->hasPendingDatagrams()) {
        //timeCount++;
        //qDebug() << "收到次数" << timeCount;

        QByteArray datagram;
        datagram.resize(m_socket->pendingDatagramSize());
        QHostAddress sender;
        quint16 senderPort;
        m_socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);

        //将收到的数据转发一份去存储
        QString fromIP = sender.toString().section(":", -1);
        emit sigSendDataToSave(datagram, fromIP, m_listenPort); //senderPort is error
        emit frameToGStream(datagram);
        emit sigSrcIP(fromIP);
    }
}

//组播模式
void ReceiveWork::startReceiving()
{
    if (m_isReceiving) return;

    if(m_bindWay == 0) {//single UDP
        initSingleUdp();
    } else if(m_bindWay == 1) { //mult UDP
        initMultiUdp();
    } else { //broad UDP
        initBroastUdp();
    }
}

void ReceiveWork::stopReceiving()
{
    timeCount = 0;
    if (!m_isReceiving)
        return;

    m_isReceiving = false;
    if(m_socket) {
        m_socket->deleteLater();
        m_socket->close();
    }
}

void ReceiveWork::closeAll()
{
    stopReceiving();
}

void ReceiveWork::initSingleUdp()
{
    bool isOK = m_socket->bind(QHostAddress(m_ip), m_listenPort, QUdpSocket::ShareAddress);
    if(isOK == false){
        qDebug()<<QString("bind失败%1").arg(m_listenPort);
        return;
    }

    connect(m_socket, &QUdpSocket::readyRead, this, &ReceiveWork::onReceive);
    m_isReceiving = true;
}

void ReceiveWork::initMultiUdp()
{
    QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();  //多网卡情况
    QNetworkInterface intf;
    QNetworkInterface intf2;
    bool findNetCard = false; //是否找到网卡
    foreach(intf, list){
        //qInfo() << "inf name:" << intf.humanReadableName() << intf.name();
        if(intf.name().contains(m_infName) == true){
            intf2 = intf;
            findNetCard = true;
            break;
        }
    }
    if(!findNetCard) {
        qDebug() << "没有找到该网卡";
        return;
    }

    //qInfo() << "intf2 name:" << intf2.name();

    bool isOK = m_socket->bind(QHostAddress(m_ip), m_listenPort, QUdpSocket::ShareAddress);
    if(isOK == false){
        qDebug()<<QString("组播bind失败%1").arg(m_listenPort)
                << m_socket->localAddress() << m_socket->localPort();
        return;
    }

    isOK = m_socket->joinMulticastGroup(QHostAddress(m_ip), intf2);
    if(isOK == false){
        qDebug()<<QString("组播jion失败%1").arg(m_ip)
                << m_socket->localAddress()<< m_socket->localPort();
        return;
    }

    connect(m_socket, &QUdpSocket::readyRead, this, &ReceiveWork::onReceive);
    m_isReceiving = true;
}

void ReceiveWork::initBroastUdp()
{
    bool isOK = m_socket->bind(m_listenPort, QUdpSocket::ShareAddress);
    if(isOK == false){
        qDebug()<<QString("bind失败%1").arg(m_listenPort);
        return;
    }

    connect(m_socket, &QUdpSocket::readyRead, this, &ReceiveWork::onReceive);
    m_isReceiving = true;
}

void ReceiveWork::setNetInfo(QString ip, quint16 port, QString infName)
{
    m_ip = ip;
    m_listenPort = port;
    m_infName = infName;
}

void ReceiveWork::init()
{
    m_isReceiving = false;
    m_socket = new QUdpSocket(this);
    emit sig_initRet(true);
}
